package com.apestech.framework.util.modul;

import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.StringUtil;
import com.esotericsoftware.reflectasm.MethodAccess;

import java.util.ArrayList;

/**
 * @author hup
 * @create 2018-12-05-16:58
 */
public class ClassMethod extends StringUtil{
    public class MethodField {
        private boolean get=false;
        private boolean set=false;
        private String field;
        private int paramCount;
        private ArrayList params;
        private int index;
        private String outputType;
        private String methodName;

        public boolean isGet() {
            return get;
        }

        public void setGet(boolean get) {
            this.get = get;
        }

        public boolean isSet() {
            return set;
        }

        public void setSet(boolean set) {
            this.set = set;
        }

        public String getField() {
            return field;
        }

        public void setField(String field) {
            this.field = field;
        }

        public int getParamCount() {
            return paramCount;
        }

        public ArrayList getParams() {
            return params;
        }

        public void setParams(ArrayList params) {
            this.params = params;
            if(params==null) this.paramCount=0;
            else this.paramCount = params.size();
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public String getOutputType() {
            return outputType;
        }

        public void setOutputType(String outputType) {
            this.outputType = outputType;
        }

        public String getMethodName() {
            return methodName;
        }

        public void setMethodName(String methodName) {
            this.methodName = methodName;
        }

    }

    private JSONObject method=new JSONObject();
    private MethodAccess access;
    private Object execclass;

    private String[] methodNames;
    private Class[][] parameterTypes;
    private Class[] returnTypes;
    private int count;
    private ArrayList<String> keylist=new ArrayList<String>();
    private String fields="";

    public ClassMethod(MethodAccess access, Object execclass) throws Exception {
        if(access==null) throw new Exception("请输入正确的CLASS名");
        this.access=access;
        this.execclass=execclass;
        this.methodNames=access.getMethodNames();
        count=this.methodNames.length;
        this.parameterTypes=access.getParameterTypes();
        this.returnTypes=access.getReturnTypes();
        init();
        count=this.keylist.size();
    }

    private void init(){
        for(int i=0; i<count; i++){
            setMethodJSON(getMethodField(methodNames[i], i));
        }
    }

    private void setMethodJSON(MethodField f){
        if(f!=null){
            String key=f.getField();
            if(f.isGet()) key="G_"+key;
            else if(f.isSet()) key="S_"+key;
            method.put(key, f);
        }
    }

    private MethodField getMethodField(String methodName, int i){
        if(methodName==null || "".equals(methodName)) return null;
        MethodField f=new MethodField();
        f.setMethodName(methodName);
        f.setIndex(i);
        String field=methodName;
        int mlen=methodName.length();
        String pre="";
        if(mlen>1) leftStr(methodName,2);
        if("is".equals(pre)){
            field=rightStr(field,mlen-2);
            if(!"".equals(field)) f.setGet(true);
        } else{
            if(mlen>2) pre=leftStr(methodName,3);
            field=rightStr(field,mlen-3);
        }
        if("get".equals(pre)){
            if(!"".equals(field)) f.setGet(true);
        }
        else if("set".equals(pre)){
            if(!"".equals(field)) f.setSet(true);
        }
        if("".equals(field)) field=methodName;
        f.setField(field);
        f.setParams(getClass(parameterTypes[i]));
        if(returnTypes[i]!=null && "void".equals(returnTypes[i].getName())){
            f.setOutputType(returnTypes[i].getName());
        }
        if(f.getOutputType()!=null && f.isGet()) f.setGet(false);
        if(f.getParamCount()!=1 && f.isSet()) f.setSet(false);
        if(f.isGet()){
            if((","+fields+",").indexOf(","+f.getField()+",")<0){
                if(!"".equals(fields)) fields=fields+",";
                keylist.add(field);
            }
        }
        return f;
    }

    private ArrayList<String> getClass(Class[] params){
        int len=params.length;
        if(len==0) return null;
        ArrayList<String> list=new ArrayList<String>();
        for(int i=0; i<len; i++){
            list.add(params[i].getName());
        }
        return list;
    }

    public MethodField getField(String field){
        if(field==null || "".equals(field.trim())) return null;
        MethodField f=null;
        Object obj=method.get(field);
        if(obj!=null) return (MethodField) obj;
        obj=method.get("G_"+field);
        if(obj!=null) return (MethodField) obj;
        obj=method.get("S_"+field);
        if(obj!=null) return (MethodField) obj;
        return f;
    }

    public int getCount() {
        return count;
    }

    public ArrayList<String> getKeylist() {
        return keylist;
    }

    public MethodAccess getAccess() {
        return access;
    }

    public Object getExecclass() {
        return execclass;
    }
}
